home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fatted Calf
/
The Fatted Calf.iso
/
Applications
/
Graphics
/
NXPlot3d
/
Source
/
Plot3DView.m
< prev
next >
Wrap
Text File
|
1994-02-20
|
22KB
|
953 lines
/* Plot3DView.m Copyright 1992 Steve Ludtke */
/* This view allows the display of 3d functions with real time rotation */
#import "Plot3DView.h"
#import "PlotShape.h"
#import "PControl.h"
#import <appkit/appkit.h>
#import <3Dkit/3Dkit.h>
#import <dpsclient/event.h>
#import <dpsclient/psops.h>
#import <stdio.h>
#import <math.h>
#include <libc.h>
#import "Expression.h"
#import "DensView.h"
void PSsethel(); /* makes Helvetica current font */
#define LRAD 10.0
extern id NXApp;
float rnd0(float x) { if (x<0) return(ceil(x)); else return floor(x); }
@implementation Plot3DView
-initFrame:(NXRect *)myrect
{
int i,j,ddl;
RtPoint fromP = {0,0,6.0}, toP = {0,0,0};
RtPoint lFromP = {5.0,10.0,5.0},lToP = {0,0,0};
RtMatrix mx = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.0 };
id aShader;
char home[60];
[super initFrame:(NXRect *)myrect];
[self setBackgroundColor:NX_COLORWHITE];
[self setDrawBackgroundColor:YES];
[self setEyeAt:fromP toward:toP roll:0.0];
mx[0][0]=mx[1][1]=mx[2][2]=3.0/fromP[2];
[self setPreTransformMatrix:mx];
aShader=[[N3DShader alloc] init];
[(N3DShader *)aShader setShader:"matte"];
shape=[[PlotShape alloc] init];
[(N3DShape *) shape setShader:aShader];
[shape scale:-1.0 :1.0 :1.0];
[[self setWorldShape:shape] free];
ambLight=[[N3DLight alloc] init];
[ambLight makeAmbientWithIntensity:0.2];
[self addLight:ambLight];
ambient=0.2;
ltheta=.785;
lchi=-.785;
aLight=[[N3DLight alloc] init];
lFromP[0]= LRAD*sin(lchi)*cos(ltheta);
lFromP[2]= LRAD*cos(lchi)*cos(ltheta);
lFromP[1]= LRAD*sin(ltheta);
[aLight makeDistantFrom:lFromP to:lToP intensity:0.8];
[self addLight:aLight];
Rmode=3;
ddl=[Window defaultDepthLimit];
if (ddl==NX_TwoBitGrayDepth||ddl==NX_EightBitGrayDepth) ddl=0;
else ddl=1;
/* initialize preferences */
for (i=0; i<MAXSETS; i++) {
pref[i].ndata=0;
pref[i].sym= -1;
if (ddl) {
pref[i].mapcol[0][0]=0.0;
pref[i].mapcol[0][1]=0.0;
pref[i].mapcol[0][2]=0.5;
pref[i].mapcol[1][0]=0.7;
pref[i].mapcol[1][1]=0.0;
pref[i].mapcol[1][2]=0.7;
pref[i].mapcol[2][0]=1.0;
pref[i].mapcol[2][1]=0.0;
pref[i].mapcol[2][2]=0.0;
pref[i].mapcol[3][0]=1.0;
pref[i].mapcol[3][1]=0.3;
pref[i].mapcol[3][2]=0.0;
pref[i].mapcol[4][0]=1.0;
pref[i].mapcol[4][1]=1.0;
pref[i].mapcol[4][2]=0.0;
}
else {
for (j=0; j<5; j++) {
pref[i].mapcol[j][0]=pref[i].mapcol[j][1]=pref[i].mapcol[j][2]=
.5+(float)j/10.0;
}
}
for (j=0; j<5; j++) pref[i].mapsel[j]=1;
pref[i].mapmode=1;
pref[i].fileData=pref[i].Sdata=NULL;
pref[i].expr=[[Expression alloc] init];
[pref[i].expr parse:"0"];
pref[i].nx=pref[i].ny=10;
}
/* initial function to display */
pref[0].sym=5;
pref[0].nx=pref[0].ny=40;
[pref[0].expr parse:"cos(sqrt(x^2+y^2)+2*pi*t)/sqrt((x+a)^2+y^2+1)"];
/* start spinning, all angles in radians */
chi=.2;
theta=.433;
/*dchi=0.025;*/
dchi=0.0;
initflag=1;
Rflags=RF_axis+RF_persp;
Omode=0;
aspect=1.0;
[shape setOver:Omode];
if (ddl) {
flagcol[0][0]=flagcol[4][0]=0.0;
flagcol[0][1]=flagcol[4][1]=0.0;
flagcol[0][2]=flagcol[4][2]=1.0;
flagcol[1][0]=flagcol[2][0]=1.0;
flagcol[1][1]=flagcol[2][1]=1.0;
flagcol[1][2]=flagcol[2][2]=1.0;
flagcol[3][0]=0.0;
flagcol[3][1]=1.0;
flagcol[3][2]=0.0;
}
else {
flagcol[0][0]=flagcol[4][0]=0.5;
flagcol[0][1]=flagcol[4][1]=0.5;
flagcol[0][2]=flagcol[4][2]=0.5;
flagcol[1][0]=flagcol[2][0]=1.0;
flagcol[1][1]=flagcol[2][1]=1.0;
flagcol[1][2]=flagcol[2][2]=1.0;
flagcol[3][0]=0.0;
flagcol[3][1]=0.0;
flagcol[3][2]=0.0;
}
[shape setFlagColors:flagcol];
[[[NXApp printInfo] setVertCentered:YES] setOrientation:NX_PORTRAIT andAdjust:YES];
[[NXApp printInfo] setMarginLeft:0.0 right:0.0 top:0.0 bottom:0.0];
[[NXApp printInfo] setHorizPagination:NX_FITPAGINATION];
[[NXApp printInfo] setVertPagination:NX_FITPAGINATION];
timer=(DPSTimedEntry)DPSAddTimedEntry(TIMESTEP,itstime,self,NX_RUNMODALTHRESHOLD);
[self zoom:self];
if (getenv("USER")!=NULL) {
sprintf(home,"/tmp/%s",getenv("USER"));
mkdir(home,0777);
}
return self;
}
/* fix the scaling after being resized */
-superviewSizeChanged:(const NXSize *)oldsize
{
[super superviewSizeChanged:oldsize];
[self zoom:self];
return self;
}
-free
{
DPSRemoveTimedEntry(timer);
[super free];
return self;
}
-drawPS:(NXRect *)myrect :(int)rectCount
{
char s[80],t[20];
int i,n,xyz[61];
float x,y,xpm,ypm,pv[61];
RtPoint pnt[61];
if (bounds.size.width<150) return self;
/* display alt and az in upper right corner */
PSsetgray(0.0);
PSsethel();
sprintf(s,"Alt:%6.2f Az:%6.2f",theta*57.295787,chi*57.295787);
PSmoveto(bounds.size.width-100.0,bounds.size.height-15.0);
PSshow(s);
PSstroke();
if (Rflags&RF_labels && Rmode<4) {
if (chi>(M_PI/2.0)&&chi<(M_PI*1.5)) ypm=1.1;
else ypm=-1.1;
if (chi<M_PI) xpm=1.1;
else xpm=-1.1;
for (n=0,y=Tick0[0],x=Tick00[0]; x<1; y+=Tick1[0],x+=Tick01[0],n++) {
if (n>59) n=59;
pnt[n][0]=x;
pnt[n][1]=ypm;
pnt[n][2]=-1.1;
pv[n]=y;
xyz[n]=0;
}
for (y=Tick0[1],x=Tick00[1]; x<1; y+=Tick1[1],x+=Tick01[1],n++) {
if (n>59) n=59;
pnt[n][1]=x;
pnt[n][0]=xpm;
pnt[n][2]=-1.1;
pv[n]=y;
xyz[n]=1;
}
for (y=Tick0[2],x=Tick00[2]; x<1; y+=Tick1[2],x+=Tick01[2],n++) {
if (n>59) n=59;
pv[n]=y;
pnt[n][2]=x;
if ((chi>M_PI/4.0&&chi<M_PI*.75)||(chi>M_PI*1.25&&chi<M_PI*1.75))
{ pnt[n][1]=ypm; pnt[n][0]=-xpm; }
else { pnt[n][1]=-ypm; pnt[n][0]=xpm; }
xyz[n]=2;
}
pnt[n][0]=xpm/1.18; pnt[n][1]=ypm/1.18; pnt[n][2]=-1.0;
[shape convertObjectPoints:pnt count:n+1 toCamera:self];
x=pnt[n][0];
for (i=0; i<n; i++) {
if (i==0|| xyz[i]!=xyz[i-1])
strcpy(t,[[tickpos cellAt:2 :xyz[i]] stringValue]);
sprintf(s,t,pv[i]);
if (pnt[i][0]<x) PSmoveto(pnt[i][0]-20.0,pnt[i][1]-5.0);
else PSmoveto(pnt[i][0],pnt[i][1]-5.0);
PSshow(s);
}
PSstroke();
}
return self;
}
/* recalculates and redisplays data */
-zoom:sender
{
float x0,x1,xs,y0,y1,ys,xf,yf,zf;
float z0,z1,x,y,z,zz,T,A,B,C,D;
int i,j=0,k,cm,nc,color[5];
id tmp;
T=[[varT cellAt:0 :0] floatValue];
A=[[varT cellAt:1 :0] floatValue];
B=[[varT cellAt:2 :0] floatValue];
C=[[varT cellAt:3 :0] floatValue];
D=[[varT cellAt:4 :0] floatValue];
/* calculate minima, maxima and step sizes */
x0=minX;
x1=maxX;
y0=minY;
y1=maxY;
xf=(x1-x0)/2.0;
yf=(y1-y0)/2.0;
/* make sure there's enough space in the data array */
for (i=0; i<NFN; i++) {
if (pref[i].sym==-1 || pref[i].fileData!=NULL) continue;
if (pref[i].ndata!=(pref[i].nx*pref[i].ny)) {
if (pref[i].ndata!=0) { free(pref[i].data); free(pref[i].color); }
pref[i].data=malloc(sizeof(Point)*(pref[i].nx*pref[i].ny+2));
pref[i].color=malloc(sizeof(RtColor)*(pref[i].nx*pref[i].ny+2));
pref[i].ndata=pref[i].nx*pref[i].ny;
}
}
z0=MAXFLOAT;
z1= -MAXFLOAT;
/* calculate (function mode) or clip (file mode) the data */
/* also finds min/max Z */
for (i=0; i<NFN; i++) {
if (pref[i].sym==-1) continue;
tmp=pref[i].expr;
[tmp setVar:"t" value:T];
[tmp setVar:"a" value:A];
[tmp setVar:"b" value:B];
[tmp setVar:"c" value:C];
[tmp setVar:"d" value:D];
/* FILE MODE */
if (pref[i].fileData!=NULL) {
k=0;
for (j=0; j<pref[i].nfdata; j++) {
if (pref[i].fileData[j].x>x1||pref[i].fileData[j].x<x0||
pref[i].fileData[j].y>y1||pref[i].fileData[j].y<y0) continue;
pref[i].data[k].x=(pref[i].fileData[j].x-x0)/xf-1.0;
[tmp setVar:"x" value:pref[i].data[k].x];
pref[i].data[k].y=(pref[i].fileData[j].y-y0)/yf-1.0;
[tmp setVar:"y" value:pref[i].data[k].y];
[tmp setVar:"z" value:pref[i].fileData[j].z];
pref[i].data[k].z=[tmp resultValue];
if (pref[i].data[k].z>z1) z1=pref[i].data[k].z;
if (pref[i].data[k].z<z0) z0=pref[i].data[k].z;
k++;
}
pref[i].ndata=k;
if (pref[i].data[0].y!=pref[i].data[1].y) {
pref[i].nx=pref[i].ny=(int)floor(sqrt((float)k));
}
else {
for (j=1; j<k; j++) if (pref[i].data[j-1].y!=pref[i].data[j].y) break;
pref[i].nx=j;
pref[i].ny=k/j;
}
}
/* FUNCTION MODE */
else {
xs=(maxX-x0)/(float)(pref[i].nx-1);
ys=(maxY-y0)/(float)(pref[i].ny-1);
x1=maxX+xs/2.0;
y1=maxY+ys/2.0;
j=0;
for (y=y0; y<y1; y+=ys) {
for (x=x0; x<x1; x+=xs) {
pref[i].data[j].x=(x-x0)/xf-1.0;
pref[i].data[j].y=(y-y0)/yf-1.0;
[tmp setVar:"x" value:x];
[tmp setVar:"y" value:y];
zz=pref[i].data[j].z=[tmp resultValue];
if (zz!=zz || zz<-MAXFLOAT || zz>MAXFLOAT)
zz=pref[i].data[j].z=0;
if (zz>z1) z1=zz;
if (zz<z0) z0=zz;
j++;
}
}
}
}
if (z0==MAXFLOAT) return self;
/* BOTH MODES */
if (z1<=z0) { z1=z0+.001; z0-=.001; }
/* allow the controller to override min/max Z */
[controller minmaxZ:&z0 :&z1];
/* tick spacing calculations */
if ([autotick intValue]) {
[self tickCalc:5.0 :x0 :x1 :&Tick0[0] :&Tick1[0]];
[[tickpos cellAt:0 :0] setFloatValue:Tick1[0]];
[[tickpos cellAt:1 :0] setFloatValue:Tick0[0]];
[self tickCalc:5.0 :y0 :y1 :&Tick0[1] :&Tick1[1]];
[[tickpos cellAt:0 :1] setFloatValue:Tick1[1]];
[[tickpos cellAt:1 :1] setFloatValue:Tick0[1]];
[self tickCalc:5.0 :z0 :z1 :&Tick0[2] :&Tick1[2]];
[[tickpos cellAt:0 :2] setFloatValue:Tick1[2]];
[[tickpos cellAt:1 :2] setFloatValue:Tick0[2]];
}
else {
Tick1[0]=[[tickpos cellAt:0 :0] floatValue];
Tick0[0]=[[tickpos cellAt:1 :0] floatValue];
Tick1[1]=[[tickpos cellAt:0 :1] floatValue];
Tick0[1]=[[tickpos cellAt:1 :1] floatValue];
Tick1[2]=[[tickpos cellAt:0 :2] floatValue];
Tick0[2]=[[tickpos cellAt:1 :2] floatValue];
}
Tick00[0]=(Tick0[0]-x0)/(x1-x0)*2.0-1.0;
Tick01[0]=Tick1[0]/(x1-x0)*2.0;
Tick00[1]=(Tick0[1]-y0)/(y1-y0)*2.0-1.0;
Tick01[1]=Tick1[1]/(y1-y0)*2.0;
Tick00[2]=(Tick0[2]-z0)/(z1-z0)*2.0-1.0;
Tick01[2]=Tick1[2]/(z1-z0)*2.0;
[shape setTicks:Tick00 :Tick01];
zf=(z1-z0)/2.0;
/* scale and clip Z */
for (i=0; i<NFN; i++) {
if (pref[i].sym==-1) continue;
/* Spherical coordinates */
if (pref[i].sym==6) {
if (pref[i].Sdata!=NULL) free(pref[i].Sdata);
pref[i].Sdata=malloc(sizeof(Point)*pref[i].ndata);
for (k=0; k<pref[i].ndata; k++) {
x=(pref[i].data[k].x+1.0)*xf+x0;
y=(pref[i].data[k].y+1.0)*yf+y0;
if (fabs(z0)>fabs(z1)) z=pref[i].data[k].z/fabs(z0);
else z=pref[i].data[k].z/fabs(z1);
if (z>1.0) z=1.0;
if (z<-1.0) z=-1.0;
pref[i].Sdata[k].x=z*cos(y)*sin(x);
pref[i].Sdata[k].y=z*sin(y)*sin(x);
pref[i].Sdata[k].z=z*cos(x);
}
}
/* color info */
cm=pref[i].mapmode;
for (j=k=0; j<5; j++) if (pref[i].mapsel[j]) { color[k]=j; k++; }
nc=k;
if (nc<2) cm=0;
for (k=0; k<pref[i].ndata; k++) {
if (pref[i].data[k].z>z1) pref[i].data[k].z=z1;
if (pref[i].data[k].z<z0) pref[i].data[k].z=z0;
z=pref[i].data[k].z=(pref[i].data[k].z-z0)/zf-1.0;
if (cm==1) {
j=floor((z+1.0)/2.00001*(float)(nc-1));
z=(z+1.0)/2.0*(float)(nc-1)-(float)j;
pref[i].color[k][0]=z*pref[i].mapcol[color[j+1]][0]+
(1.0-z)*pref[i].mapcol[color[j]][0];
pref[i].color[k][1]=z*pref[i].mapcol[color[j+1]][1]+
(1.0-z)*pref[i].mapcol[color[j]][1];
pref[i].color[k][2]=z*pref[i].mapcol[color[j+1]][2]+
(1.0-z)*pref[i].mapcol[color[j]][2];
}
}
}
/* display 3d plot */
[shape setData:pref :Rmode :Rflags];
[shape setAng:theta :chi :aspect :ambient];
[self display];
/* display density plot */
[controller updDen:Tick00 :Tick01];
return self;
}
/* obvious */
-setAng:(float)alt :(float)az
{
theta=alt;
chi=az;
return self;
}
/* allows spinning and zooming with the mouse */
-mouseDown:(NXEvent *)oevent
{
int oldMask,loop=1;
float ix=0,iy=0,ix2=0,iy2=0;
NXEvent *event,evs;
long tm,tm2;
evs=*oevent;
oevent=&evs;
[self convertPoint:&oevent->location fromView:nil];
oevent->location.x=oevent->location.x/bounds.size.width*2.0-1.0;
oevent->location.y=oevent->location.y/bounds.size.height*2.0-1.0;
ix2=ix=oevent->location.x;
iy2=iy=oevent->location.y;
tm2=tm=oevent->time;
oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];
while (loop) {
event = [NXApp getNextEvent:(NX_LMOUSEUPMASK | NX_LMOUSEDRAGGEDMASK)];
[self convertPoint:&event->location fromView:nil];
event->location.x=event->location.x/bounds.size.width*2.0-1.0;
event->location.y=event->location.y/bounds.size.height*2.0-1.0;
switch (event->type) {
case NX_LMOUSEUP:
loop = 0;
dchi=-(event->location.x-ix2)/(float)(event->time-tm2)*15.0;
if (fabs(dchi)<.004) dchi=0.0;
[shape setAng:theta :chi :aspect :ambient];
[self display];
break;
case NX_LMOUSEDRAGGED:
theta-=(event->location.y-iy)*3.0;
chi-=(event->location.x-ix)*4.0;
if (theta>M_PI/2.0) theta=M_PI/2.0;
if (theta<-M_PI/2.0) theta=-M_PI/2.0;
while (chi>2.0*M_PI) chi-=2.0*M_PI;
while (chi<0.0) chi+=2.0*M_PI;
ix2=ix;
iy2=iy;
tm2=tm;
ix=event->location.x;
iy=event->location.y;
tm=event->time;
[shape setAng:theta :chi :aspect :ambient];
[self display];
break;
default:
break;
}
}
[window setEventMask:oldMask];
return self;
}
/* function called by timer */
void itstime(DPSTimedEntry entry,double now,id call)
{
[call step];
return;
}
/* do one time step */
-step
{
if (initflag) {
/* first time, do initialization stuff */
if (controller==nil) return self;
[controller startup:pref];
[self setSurfaceTypeForAll:N3D_SmoothSolids chooseHider:YES];
[self zoom:self];
initflag=0;
}
if (dchi==0.0) return self;
chi+=dchi;
while (chi>2.0*M_PI) chi-=2.0*M_PI;
while (chi<0.0) chi+=2.0*M_PI;
[shape setAng:theta :chi :aspect :ambient];
[self display];
return self;
}
-tickCalc:(float)n :(float)x0 :(float)x1 :(float *)min :(float *)spa
{
float s,e;
s=(x1-x0)/n;
e=floor(log10(s));
if (s/pow(10.0,e)<3.0) s=floor(s/pow(10.0,e-1.0))*pow(10.0,e-1.0);
else s=floor(s/pow(10.0,e))*pow(10.0,e);
*min=(floor(x0/s)+1.0)*(s);
*spa=s;
return self;
}
/* new min/max values */
-zoomTo:(float)minx :(float)miny :(float)maxx :(float)maxy
{
minX=minx;
minY=miny;
maxX=maxx;
maxY=maxy;
return self;
}
-(int)acceptsFirstMouse { return (YES); }
-setcontroller:con
{
controller=con;
return self;
}
/* allow user to pause spinning */
-togFreeze:sender
{
static float Tdchi;
if ([sender intValue]) {
Tdchi=dchi;
dchi=0.0;
return self;
}
dchi=Tdchi;
return self;
}
- renderSelf:(RtToken)context
{
return self;
}
-makeSMap:sender
{
FILE *out;
char home[60],s[80];
id image,rep;
NXSize size = { 400.0,400.0 };
NXStream *stream;
float xs,ys,x,y,xpm,ypm,fs;
int r;
sprintf(home,"/tmp/%s",getenv("USER"));
if (getenv("USER")==NULL) strcpy(home,"/tmp");
/* write maps for axis labels */
if (Rflags&RF_labels) {
[window setTitle:"Generating Axis Label Maps"];
if (chi>(M_PI/2.0)&&chi<(M_PI*1.5)) ypm=1.0;
else ypm=-1.0;
if (chi<M_PI) xpm=1.0;
else xpm=-1.0;
r=floor(chi/M_PI*4.0);
image=[[NXImage alloc] initSize:&size];
[image setCacheDepthBounded:NO];
[image useCacheWithDepth:NX_TwentyFourBitRGBDepth];
rep=[image lastRepresentation];
[rep setAlpha:NO];
[rep setNumColors:3];
[image lockFocus];
PSselectfont("Helvetica-Bold",fs=[fontSize floatValue]);
PSsetrgbcolor(1.0,.95,1.0);
PSmoveto(0,0);
PSlineto(1.0,1.0);
PSstroke();
PSsetrgbcolor(0,0,0);
strcpy(s,[[axisTitle cellAt:0 :0] stringValue]);
PSstringwidth(s,&xs,&ys);
PSmoveto((size.width-xs)/2.0,size.height/4.0-fs*2.0-10.0);
PSshow(s);
for (y=Tick0[0],x=Tick00[0]; x<1; y+=Tick1[0],x+=Tick01[0]) {
sprintf(s,[[tickpos cellAt:2 :0] stringValue],y);
PSstringwidth(s,&xs,&ys);
if (ypm<0)
PSmoveto((x+1.0)*size.width/2.0-xs/2.0-1.0,size.height/4.0-fs-6.0);
else PSmoveto(size.width*(1.0-x)/2.0-xs/2.0-1.0,size.height/4.0-fs-6.0);
PSshow(s);
}
PSstroke();
strcpy(s,[[axisTitle cellAt:1 :0] stringValue]);
PSstringwidth(s,&xs,&ys);
PSmoveto((size.width-xs)/2.0,size.height/2.0-fs*2.0-10.0);
PSshow(s);
for (y=Tick0[1],x=Tick00[1]; x<1; y+=Tick1[1],x+=Tick01[1]) {
sprintf(s,[[tickpos cellAt:2 :1] stringValue],y);
PSstringwidth(s,&xs,&ys);
if (xpm>0)
PSmoveto((x+1.0)*size.width/2.0-xs/2.0-1.0,size.height/2.0-fs-6.0);
else PSmoveto(size.width*(1.0-x)/2.0-xs/2.0-1.0,size.height/2.0-fs-6.0);
PSshow(s);
}
PSstroke();
PSgsave();
strcpy(s,[[axisTitle cellAt:2 :0] stringValue]);
PSstringwidth(s,&xs,&ys);
PStranslate(size.width/2.0,size.height*3.0/4.0);
if (r%2==1) PSrotate(180.0);
PSmoveto(-xs/2.0,0.0);
PSshow(s);
PSstroke();
PSgrestore();
PSgsave();
PSrotate(90.0);
PStranslate(size.height/2.0,-size.width);
for (y=Tick0[2],x=Tick00[2]; x<1; y+=Tick1[2],x+=Tick01[2]) {
sprintf(s,[[tickpos cellAt:2 :2] stringValue],y);
PSstringwidth(s,&xs,&ys);
if (r%2==1)
PSmoveto(size.height/2.0-xs-2.0,(x+1.0)*(size.width)/2.0-8.0);
else PSmoveto(8.0,(x+1.0)*(size.width)/2.0-8.0);
PSshow(s);
}
PSstroke();
PSgrestore();
[image unlockFocus];
stream=NXOpenMemory(NULL,0,NX_WRITEONLY);
[image writeTIFF:stream];
sprintf(s,"%s/plot3dxyz.tiff",home);
NXSaveToFile(stream,s);
NXClose(stream);
[image free];
sprintf(s,"%s/plot3d.rib",home);
out=fopen(s,"w");
fprintf(out,"MakeTexture \"%s/plot3dxyz.tiff\" \"%s/plot3dxyz.tx\" \"clamp\" \"black\" \"box\" 1 1\n",home,home);
fclose(out);
sprintf(s,"/usr/prman/prman %s/plot3d.rib",home);
system(s);
[window setTitle:"3D"];
}
if (Omode==0||Omode==OVER_csurf) return self;
[window setTitle:"Generating Surface Map"];
/* make map of contour/density plot */
[controller dumpContour];
sprintf(s,"%s/plot3d.rib",home);
out=fopen(s,"w");
fprintf(out,"MakeTexture \"%s/plot3d.tiff\" \"%s/plot3d.tx\" \"black\" \"black\" \"gaussian\" 1.8 1.8\n",home,home);
fclose(out);
sprintf(s,"/usr/prman/prman %s/plot3d.rib",home);
system(s);
[window setTitle:"3D"];
return self;
}
- dumpRib:sender
{
static id savePanel=nil;
NXStream *ts;
char buf[MAXPATHLEN+1];
if (!savePanel) {
savePanel=[SavePanel new];
[savePanel setRequiredFileType:"rib"];
}
Rmode+=4;
[shape setData:pref :Rmode :Rflags];
if([savePanel runModal]){
[self makeSMap:self];
ts=NXOpenMemory(NULL, 0, NX_WRITEONLY);
strcpy(buf, [savePanel filename]);
strrchr(buf,'.')[0]='\0';
NXPrintf(ts, "Display \"%s.tiff\" \"file\" \"rgba\"\n", buf);
[self copyRIBCode:ts];
NXSaveToFile(ts, [savePanel filename]);
NXCloseMemory(ts,NX_FREEBUFFER);
}
Rmode-=4;
[shape setData:pref :Rmode :Rflags];
return self;
}
-PRTiff:sender
{
static id savePanel=nil;
if (!savePanel) {
savePanel=[SavePanel new];
[savePanel setRequiredFileType:"tiff"];
}
if([savePanel runModal]) [self renderTIFF:[savePanel filename]];
return self;
}
- renderTIFF:(char *)fsp
{
NXStream *ts;
char buf[MAXPATHLEN+1];
char home[60];
sprintf(home,"/tmp/%s",getenv("USER"));
if (getenv("USER")==NULL) strcpy(home,"/tmp");
Rmode+=4;
[shape setData:pref :Rmode :Rflags];
[self makeSMap:self];
[window setTitle:"Rendering TIFF"];
ts=NXOpenMemory(NULL, 0, NX_WRITEONLY);
NXPrintf(ts, "Display \"%s\" \"file\" \"rgba\"\n", fsp);
[self copyRIBCode:ts];
sprintf(buf,"%s/plot3dp.rib",home);
NXSaveToFile(ts, buf);
NXCloseMemory(ts,NX_FREEBUFFER);
[shape setData:pref :Rmode :Rflags];
Rmode-=4;
sprintf(buf,"/usr/prman/prman %s/plot3dp.rib",home);
system(buf);
[window setTitle:"3D"];
return self;
}
- setAmbLight:sender
{
[ambLight setIntensity:ambient=[sender floatValue]];
[self display];
return self;
}
- setLight:sender
{
[aLight setIntensity:[sender floatValue]];
[self display];
return self;
}
-setLightX:sender
{
RtPoint from;
lchi= -[sender floatValue];
from[0]= LRAD*sin(lchi)*cos(ltheta);
from[2]= LRAD*cos(lchi)*cos(ltheta);
from[1]= LRAD*sin(ltheta);
[aLight setFrom:from];
[self display];
return self;
}
-setLightY:sender
{
RtPoint from;
ltheta=[sender floatValue];
from[0]= LRAD*sin(lchi)*cos(ltheta);
from[2]= LRAD*cos(lchi)*cos(ltheta);
from[1]= LRAD*sin(ltheta);
[aLight setFrom:from];
[self display];
return self;
}
- setMode:sender
{
int i;
Rmode=i=[sender selectedRow];
switch(i) {
case 0:
[self setSurfaceTypeForAll:N3D_PointCloud chooseHider:YES];
[window setDepthLimit:NX_TwoBitGrayDepth];
break;
case 1:
[self setSurfaceTypeForAll:N3D_WireFrame chooseHider:YES];
[window setDepthLimit:NX_TwoBitGrayDepth];
break;
case 2:
[self setSurfaceTypeForAll:N3D_FacetedSolids chooseHider:YES];
break;
case 3:
[self setSurfaceTypeForAll:N3D_SmoothSolids chooseHider:YES];
break;
}
[shape setData:pref :Rmode :Rflags];
[self display];
return self;
}
-setOverlay:sender
{
Omode=0;
if ([[sender cellAt:0 :0] intValue]) Omode+=OVER_surf;
if ([[sender cellAt:1 :0] intValue]) Omode+=OVER_csurf;
if ([[sender cellAt:2 :0] intValue]) Omode+=OVER_base;
[shape setOver:Omode];
return self;
}
-printPSCode:sender
{
[self makeSMap:self];
Rmode+=4;
[shape setData:pref :Rmode :Rflags];
[super printPSCode:sender];
Rmode-=4;
[shape setData:pref :Rmode :Rflags];
return self;
}
-setFlags:sender
{
Rflags=0;
if ([[flagSel findCellWithTag:0] intValue]) Rflags+=RF_axis;
if ([[flagSel findCellWithTag:1] intValue]) Rflags+=RF_backs;
if ([[flagSel findCellWithTag:2] intValue]) Rflags+=RF_floor;
if ([[flagSel findCellWithTag:3] intValue]) Rflags+=RF_ticks;
if ([[flagSel findCellWithTag:4] intValue]) Rflags+=RF_planes;
if ([[flagSel findCellWithTag:5] intValue]) Rflags+=RF_labels;
[shape setData:pref :Rmode :Rflags];
[self display];
return self;
}
-setFlagColor:sender
{
int i;
i=[sender tag];
NXConvertColorToRGB([sender color],
&flagcol[i][0],&flagcol[i][1],&flagcol[i][2]);
[shape setFlagColors:flagcol];
[self display];
return self;
}
-size320:sender
{
[[self window] sizeWindow:325 :204];
return self;
}
-setEye:sender
{
RtPoint fromP = {0,0,6.0},toP={0.0,0.0,0.0};
RtMatrix mx = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.0 };
fromP[2]=[sender floatValue];
[self setEyeAt:fromP toward:toP roll:0.0];
mx[0][0]=mx[1][1]=mx[2][2]=3.0/fromP[2];
[self setPreTransformMatrix:mx];
[self display];
return self;
}
-setAsp:sender
{
aspect=[sender floatValue];
[shape setAng:theta :chi :aspect :ambient];
[self display];
return self;
}
-setProj:sender
{
if ([sender intValue]) {
[self setProjection:N3D_Perspective];
Rflags|=RF_persp;
[self setUsePreTransformMatrix:NO];
}
else {
[self setProjection:N3D_Orthographic];
Rflags&=(~RF_persp);
[self setUsePreTransformMatrix:YES];
}
[self display];
return self;
}
-(float)getTheta
{
return(theta);
}
-(float)getChi
{
return(chi);
}
-aspect11:sender
{
[aspectS setFloatValue:1.0];
aspect=1.0;
[shape setAng:theta :chi :aspect :ambient];
[self display];
return self;
}
@end